const path = require('path');
const jsonfile = require('jsonfile');
const _ = require('lodash');
const app = require('../server');
const services = require('../services');

const settings = jsonfile.readFileSync(path.join(__dirname, 'audit-field-mixin.json'));
const commonService = services.common;

module.exports = function(Model, options) { // eslint-disable-line
  attachProperties(Model, options);
  attachRelations(Model, options);
  attachOperationHooks(Model, options);
  attachACLs(Model, options);
  overrideRemoteMethods(Model, options);
};

function attachProperties(Model, options) { // eslint-disable-line
  _.forEach(settings.properties, (setting, name) => {
    Model.defineProperty(name, setting);
  });
}

function overrideRemoteMethods(Model, options) { // eslint-disable-line
  // Model.defaultScope = (query, inst) => ({ where: { deleted: false } }); // eslint-disable-line
  // Model.deleteById = (id, opts, cb) => {
  //   Model.update({ id }, { deleted: true }, cb);
  // };
}

function attachOperationHooks(Model, options) { // eslint-disable-line
  Model.observe('before save', (ctx, next) => {
    const employeeId = commonService.getEmployeeId();
    if (_.isEmpty(employeeId)) return next();
    if (ctx.isNewInstance && ctx.instance) { // create
      ctx.instance.sys_owner = employeeId;
      ctx.instance.sys_created_by = employeeId;
      ctx.instance.sys_updated_by = employeeId;
    } else if (ctx.instance) { // replace
      ctx.instance.sys_updated_by = employeeId;
      ctx.instance.sys_updated_at = new Date();
    } else if (ctx.data) { // update
      ctx.data.sys_updated_by = employeeId;
      ctx.data.sys_updated_at = new Date();
    }
    return next();
  });
}


function attachRelations(Model, options) {
  const userModel = app.models[options.userModel];
  if (userModel) {
    defineRelations(Model, options, settings.relations);
  } else {
    app.datasources.pg.modelBuilder.models[options.userModel].on('attached', () => {
      defineRelations(Model, options, settings.relations);
    });
  }
}

function defineRelations(Model, options, relations) {
  _.forEach(relations, (setting, name) => {
    Model.belongsTo(app.models[options.userModel], _.assign(setting, { as: name, primaryKey: 'employeeId' }));
  });
}

function attachACLs(Model, options) {
  const ACL = app.models.ACL;
  if (ACL) {
    createACLs(Model, options);
  } else {
    app.datasources.pg.modelBuilder.models.ACL.on('attached', () => {
      createACLs(Model, options);
    });
  }
}

function createACLs(Model, options) {
  // app.models.ACL.create({
  //   model: Model.definition.name,
  //   property: 'sys_updated_by',
  //   accessType: 'WRITE',
  //   principalType: 'ROLE',
  //   principalId: '$everyone',
  //   permission: 'DENY',
  // }, (err, acl) => {
  //   console.log('ACL entry created: %j', acl);
  // });
}
